package com.example.nettydemo.simple;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;

/**
 * Netty 客户端
 *
 * @author SuperWein
 */
@Slf4j
public class NettyClient {
    // 自定义分隔符
    private static final String ascii2 = String.valueOf((char)2);
    private static final String ascii3 = String.valueOf((char) 3);

    public void connect(String ip, int port) {
        // 定义服务类
        Bootstrap bootstrap = new Bootstrap();
        // 定义执行线程组
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 设置直线线程组和通道
            bootstrap.group(workerGroup).channel(NioSocketChannel.class)
                    // 维持链接的活跃
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    // 关闭延迟发送
                    .option(ChannelOption.TCP_NODELAY, true)
                    // 设置handler, 管道中的处理器
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            // 利用DelimiterBasedFrameDecoder解决TCP的粘包/拆包的问题
                            // 如果读取到客户端发送的内容长度大于1024个字节，默认接收的时候会被拆包
                            channel.pipeline().addLast(new DelimiterBasedFrameDecoder(2048,
                                    false, false, Unpooled.copiedBuffer(ascii3.getBytes())));
                            // 设置管道读写编码
                            channel.pipeline().addLast(new StringEncoder(Charset.forName("utf-8")));
                            channel.pipeline().addLast(new StringDecoder(Charset.forName("utf-8")));
                            // 设置管道处理器
                            channel.pipeline().addLast(new ChannelClientHandler());
                        }
                    });
            // 创建连接
            ChannelFuture future = bootstrap.connect(ip, port).sync();
            // 写入数据
            future.channel().writeAndFlush( ascii2 + "hello server, I'm client." + ascii3 + "哈哈哈哈哈" + ascii3);
            // 等待，直到连接关闭继续往下执行
            future.channel().closeFuture().sync();
            // 测试在Console控制台输入
//            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
//            while(true){
//                System.out.println("请输入：");
//                String msg = bufferedReader.readLine();
//                future.channel().writeAndFlush(msg);
//            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭释放资源
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new NettyClient().connect("10.20.132.11", 8888);
    }

}
